package com.iflytek.rule.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.iflytek.rule.enums.CodeEnums;
import com.iflytek.rule.exceptions.BusinessException;
import com.iflytek.rule.model.RuleResultModel;
import com.iflytek.rule.strategy.ValueEngineStrategy;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author weibi
 * @Date 2020/3/4 15:39
 * @Version 1.0
 * @Description TODO
 **/
public class Utils {


    /**
     * 获取当前日期：yyyy-MM-dd格式
     *
     * @return Date
     */
    public static Date getCurrentDate(String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        String currentDateStr = dateFormat.format(new Date());
        Date currentDate = null;
        try {
            currentDate = dateFormat.parse(currentDateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return currentDate;
    }


    /**
     * 获取 如 </#></TransactionCode></Req> 中 TransactionCode 节点
     *
     * @param str
     * @return
     */
    public static String getXmlNode(String str) {
        String res = str.replace("</#>", "");
        return res.substring(res.indexOf("</") + 2, res.indexOf(">"));
    }

    /**
     * 获取 <#></#>
     *
     * @param str
     * @param map
     * @param type
     * @return
     */
    public static Map<String, Object> getParamValue1(String str, Map<String, Object> map, String type) {
        String con = "(<#>)([^>]*)<";
        Pattern pat = Pattern.compile(con);
        Matcher m = pat.matcher(str);
        while (m.find()) {
            String language = m.group(2);
            String node = "";
            if ("xml".equals(type)) {
                node = getXmlNode(str.substring(str.indexOf(language)));
            } else if ("json".equals(type)) {
                node = getJsonNode(str.substring(0, str.indexOf(language)));
            }
            map.put(node, language);
            str = str.replace(str.substring(0, str.indexOf(language)), "");
            getParamValue1(str, map, type);
        }
        return map;
    }

    private static String getJsonNode(String substring) {
        String str = substring.substring(substring.lastIndexOf(",") + 1);
        String node = str.substring(0, str.lastIndexOf(":") - 1).trim().replace("\"", "");
        return node;
    }

    /**
     * 截取字符串中 以 <#>开始</#>结尾 中间的部分
     *
     * @param value
     * @return
     */
    public static Map<String, Object> getParamValue(String value, String type) {

        Map<String, Object> map = new HashMap<>();
        return getParamValue1(value, map, type);
    }

    /**
     * 去除
     * 注：\n 回车(\u000a)
     * \t 水平制表符(\u0009)
     * \s 空格(\u0008)
     * \r 换行(\u000d)
     *
     * @param str
     * @return
     */
    public static String replaceBlank(String str) {
        String dest = "";
        if (str != null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
    }


    public static String toStr(String str,
                               Map<String, Object> map,
                               Object object) {

        // 规则：{} 说明在map中已经有该字段，这个字段在数据库必须是在前面
        if (str.indexOf("{") > -1) {
            str = str.substring(1, str.length() - 1);
            return (String) map.get(str);
        } else if (str.indexOf("attr[") > -1) { // 需要入参对象属性值
            str = str.replace("attr[", "").replace("]", "");
            str = (String) ReflectUtil.getFieldValue(object, str);
        }

        return str;
    }

    public static String getStrType(String str) {
        if (str.startsWith("<")) {
            return "xml";
        } else if (str.startsWith("{")) {
            return "json";
        }
        return null;
    }

    /**
     * 解析mapping
     *
     * @param mapping
     */
    public static Map<String, String> parseMapping(String mapping) {

        String[] mappingArr = mapping.split("\\$");
        String mr0 = mappingArr[0];
        String resmr0 = mr0.substring(1, mr0.length() - 1);
        String[] childArr0 = resmr0.split("\\,");

        String mr1 = mappingArr[1];
        String resmr1 = mr1.substring(1, mr1.length() - 1);
        String[] childArr1 = resmr1.split("\\,");

        Map<String, String> map = new LinkedHashMap<>();
        for (int i = 0, len = childArr0.length; i < len; i++) {
            map.put(childArr0[i], childArr1[i]);
        }
        return map;

    }

    public static String filter(String value, String param) {
        if (StrUtil.isBlank(param)) {
            return value;
        }
        String[] strArr = param.split("\\,");
        for (String str : strArr) {
            value = value.replace(str, "");
        }
        return value;
    }

    /**
     * 目前不支持子孙节点
     *
     * @param nodes
     * @param object
     * @return
     */
    public static Object getNodeValue(String nodes, JSONObject object) {
        String[] listNodeArr = nodes.split("\\>");
        Object obj = null;
        JSONObject response = null;
        for (int i = 0, len = listNodeArr.length; i < len; i++) {

            // 不是最后一个节点
            if (i != listNodeArr.length - 1) {
                if (null == response) {
                    response = (JSONObject) object.get(listNodeArr[i]);
                } else {
                    response = (JSONObject) response.get(listNodeArr[i]);
                }
            }
            // 最后一个节点
            if (i == listNodeArr.length - 1) {
                if (null == response) {
                    response = object;
                }
                obj = response.get(listNodeArr[listNodeArr.length - 1]);
            }
        }
        return obj;

    }

    /**
     * 将值填充到入参中
     *
     * @param requestParam
     * @param newMap
     * @param oldMap
     * @return
     */
    public static String mapToParam(String requestParam, Map<String, Object> newMap, Map<String, Object> oldMap) {

        String resStr = requestParam.replace("<#>", "").replace("</#>", "");
        for (Map.Entry<String, Object> map : oldMap.entrySet()) {
            String key = map.getKey();
            String oldValue = String.valueOf(map.getValue());
            String newValue = String.valueOf(newMap.get(key));
            if ("null".equals(newValue)) {
                newValue = "";
            }
            resStr = resStr.replace(oldValue, newValue);
        }
        return resStr;

    }


    public static Map<String, Object> paramToMap(Map<String, Object> map,
                                                 Object object) {

        Map<String, Object> tmpMap = new HashMap<>(map.size());
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = (String) entry.getValue();
            if (value.indexOf("#") > -1) {
                // java#类#方法 、 js#方法#代码、attr#属性、固定值（固定值没有前缀，无需做操作）
                Object objValue = ValueEngineStrategy.getInstance().
                        getValue(tmpMap, object, value);
                tmpMap.put(key, objValue);

            } else {
                // 固定值不处理
                tmpMap.put(key, value);
            }
        }

        return tmpMap;

    }


    public static Object getResult(
            RuleResultModel resultModel,
            JSONObject object
    ) {
        String returnCodeNode = resultModel.getReturnCodeNode();

        String[] codeNodeArr = returnCodeNode.split("\\>");
        String[] codeArr = codeNodeArr[codeNodeArr.length - 1].split("\\=");
        String code = codeArr[1];

        returnCodeNode = returnCodeNode.substring(0, returnCodeNode.indexOf("="));
        String returnCode = getReturnCode(object, returnCodeNode);


        Object obj = null;
        if (code.equals(returnCode)) {
            String listNode = resultModel.getListNode();
            obj = Utils.getNodeValue(listNode, object);
        } else {
            System.out.println("返回code异常！！" + returnCode);
            JSONObject err = new JSONObject();
            err.put("code", returnCode);
            err.put("merchantErrMsg", Utils.getNodeValue(resultModel.getReturnMsgNode(), object));
            return err;

        }
        return obj;
    }

    private static String getReturnCode(JSONObject object, String returnCodeNode) {
        return String.valueOf(Utils.getNodeValue(returnCodeNode, object));

    }


    /**
     * 设置缓存key
     *
     * @param hospitalEname
     * @param xfRequestMethod
     * @return
     */
    public static String setRedisKey(String hospitalEname,
                                     String xfRequestMethod,
                                     String type) {
        StringBuffer buffer = new StringBuffer();
        buffer.append("rule-engine:cache:").
                append(hospitalEname).append(":").
                append(xfRequestMethod).
                append(":").append(type);
        return buffer.toString();
    }


    public static Object rpcResult(Object res,
                                   String resObjPath,
                                   RuleResultModel resultModel) {

        if (ObjectUtil.isNull(res)) {
            System.out.println("接口返回解析数据异常");
            throw new BusinessException(CodeEnums.RESULT_DATA_ERROR);
        }


        JSONArray array = null;
        if (res instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject) res;
            array = new JSONArray();
            array.add(jsonObject);
        } else if (res instanceof JSONArray) {
            array = (JSONArray) res;
        }

        if (null == array || array.size() == 0) {
            return new ArrayList<>();
        }

        List<Object> resList = new ArrayList<>(array.size());
        String mappingStr = StrUtil.trim(resultModel.getMapping());

        array.forEach(item ->
        {
            JSONObject json = (JSONObject) item;
            Object resObj = null;
            try {
                Class clazz = Class.forName(resObjPath);
                resObj = clazz.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            Map<String, String> tmpMap = Utils.parseMapping(mappingStr);
            Map<String, Object> map = new HashMap<>(tmpMap.size());
            for (Map.Entry<String, String> entry : tmpMap.entrySet()) {
                String val = entry.getValue();
                if (val.indexOf("#") > -1) {
                    Object obj = ValueEngineStrategy.getInstance().getValue(map, resObj, val);
                    ReflectUtil.setFieldValue(resObj, entry.getKey(), obj);
                } else {
                    String str = json.getStr(val);
                    map.put(entry.getKey(), str);
                    ReflectUtil.setFieldValue(resObj, entry.getKey(), str);
                }
            }
            resList.add(resObj);
        });
        return resList;

    }


    /**
     * 获取时间集合
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    public static List<String> getDateRegion(String startDate, String endDate) {
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Calendar cStart = Calendar.getInstance();
            cStart.setTime(dateFormat.parse(startDate));
            List<String> dateList = new ArrayList();
            //别忘了，把起始日期加上
            dateList.add(startDate);
            // 此日期是否在指定日期之后
            Date dEnd = dateFormat.parse(endDate);
            while (dEnd.after(cStart.getTime())) {
                // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
                cStart.add(Calendar.DAY_OF_MONTH, 1);
                dateList.add(dateFormat.format(cStart.getTime()));
            }
            return dateList;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String dateToWeek(String datetime) {
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
        Calendar cal = Calendar.getInstance(); // 获得一个日历
        Date datet = null;
        try {
            datet = f.parse(datetime);
            cal.setTime(datet);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的某天。
        if (w < 0) {
            w = 0;
        }
        return weekDays[w];
    }


    /**
     * 合并所有JSONObject
     *
     * @param jsons
     * @return
     */
    public static JSONObject combineJson(JSONObject... jsons) {

        JSONObject json = new JSONObject();
        if (jsons.length == 0) {
            return json;
        }

        for (int i = 0; i < jsons.length; i++) {
            JSONObject jsonObject = jsons[i];
            if (ObjectUtil.isEmpty(jsonObject)) {
                continue;
            }

            Set<String> keys = jsonObject.keySet();
            for (String s : keys) {
                json.put(s, jsonObject.get(s));
            }
        }
        return json;
    }

    public static void main(String[] args) {
    }
}
